<?php
include_once("core/libs/".$configDBchoice.".php");


/**
 * Interface class between user and DataBase
 * It provides an abstraction layer
 *
 * @copyright inovia
 * @package oolime_core   
 */
class Database {
    
  private $connection;
  private $isConnected = false;
  private $numQueries;
  private $logFile;
  private $explainAll;
  private $logs;
    
    /**
     * Constructor making a database connection
     *
     * @param string $host
     * @param string $username
     * @param string $password
     * @param string $database
     * @param int $port
     * @todo raise error
     */
    public function __construct(){  
        global $configDataBaseExplainAll;  
        global $configLogDataBaseFile;
        global $logs;
        $this->logFile    = $configLogDataBaseFile;
        $this->explainAll = $configDataBaseExplainAll;
        $this->logs       = &$logs;
    }
    
    /**
     * makes the request
     *
     * @param string $request the SQL request
     * @return mixed the result of the query
     */
    public function queries($request){
      $this->connect();
        $this->numQueries++;
        if($this->explainAll) $this->explainedQueries($request);
        try {
        	$result = $this->connection->query($request);
        	return $result;
        } catch(Exception $e) {
          $this->logs->logError($e->getMessage());
        }
    }

    /**
     * Tells if the connection is established
     * @return bool indicates the state of the connection 
     */         
    public function isConnectd(){
      return $this->isConnected;
    }

    /**
     * saves defined tables in a file
     *
     * @param : $tables - Array - DataBase Tables Array
     * @param : $file - string - The file where we have to save
     */
    public function exportTables($tables, $file) {
      $this->connect();
         if(count($tables)>0) {
            $search   = Array("\x00","\x0a","\x0d","\x1a");
            $replace  = Array('\0','\n','\r','\Z');
            $file     = new File($file,"w","gzip");

             while(list($key,$val) = each($tables)) {
                     
                 try {
                   // save of table's creation
                   $tmp = "/*\nWe create the table \"".$val."\"\n*/\n";
                   $req = "SHOW CREATE TABLE `".$val."` ;";
                   $row = $this->queries($req)->fetch_row();
                   $tmp .= preg_replace("/^CREATE TABLE/","CREATE TABLE IF NOT EXISTS",$row[1]);
                   $file->writeAll($tmp." ;\n\n");

                   // save of table's data
                   $tmp = "/*\nWe insert old values in \"".$val."\"\n*/\n";
                   $file->writeAll($tmp);
                   $req = "SELECT * FROM `".$val."` ;";
                   $result = $this->queries($req);
                   $numFields = $result->num_fields();
                
                   while($row = $result->fetch_row()) {
                     
                        $temp = "INSERT INTO `".$val."` VALUES (";
                        $stamp = "";
                        for($i=0;$i<$numFields;$i++) {
                           $temp .= $stamp."\"".str_replace($search,$replace,addslashes($row[$i]))."\"";
                           $stamp = ", ";
                        }
                        $temp .= ") ;\n";
                        $file->writeAll($temp);
                   }
                   $file->writeAll("\n\n\n");
                } catch(Exception $e) {
                  $this->logs->logError($e->getMessage());
                }
             }
         }
    }
    
    
        /**
     * saves defined tables in a file
     *
     * @param : $tables - Array - DataBase Tables Array
     * @param : $file - string - The file where we have to save
     * @param : $pattern - string - The explain of WHERE clause     
     */
    public function exportFilterTables($tables, $file,$pattern) {
      $this->connect();
         if(count($tables)>0) {
            $search = Array("\x00","\x0a","\x0d","\x1a");
            $replace = Array('\0','\n','\r','\Z');
            $file = new File($file,"w","gzip");

             while(list($key,$val) = each($tables)) {
                     
                  try{
                   // save of table's creation
                   $tmp = "/*\nWe create the table \"".$val."\"\n*/\n";
                   $req = "SHOW CREATE TABLE `".$val."` ;";
                   $row = $this->queries($req)->fetch_row();
                   $tmp .= preg_replace("/^CREATE TABLE/","CREATE TABLE IF NOT EXISTS",$row[1]);
                   $file->writeAll($tmp." ;\n\n");

                   // save of table's data
                   $tmp = "/*\nWe insert old values in \"".$val."\"\n*/\n";
                   $file->writeAll($tmp);
                   $req = "SELECT * FROM `".$val."` WHERE ".$pattern.";";
                   $result = $this->queries($req);
                   $numFields = $result->num_fields();
                   while($row = $result->fetch_row()) {
                     
                        $temp = "INSERT INTO `".$val."` VALUES (";
                        $stamp = "";
                        for($i=0;$i<$numFields;$i++) {
                           $temp .= $stamp."\"".str_replace($search,$replace,addslashes($row[$i]))."\"";
                           $stamp = ", ";
                        }
                        $temp .= ") ;\n";
                        $file->writeAll($temp);
                   }
                   $file->writeAll("\n\n\n");
                } catch(Exception $e) {
                  $this->logs->logError($e->getMessage());
                }
             }
         }
    }
    





    
    /**
     * makes the request and EXPLAIN it into a logfile
     *
     * @param string $request the SQL request
     * @return string the result of the explain
     * @todo Raise errors
     */
    public function explainedQueries($request){
        $this->connect();
        include_once("core/libs/file.php");
        $this->numQueries++;
        $request = "EXPLAIN ".$request;
        try {
          $result   = $this->connection->query($request);
          if(!$result) exit;
          $response = "<br /><br /><table border=1 bordercolor=#000000 cellspacing=0 colspacing=0>
                  <tr>
                      <td colspan=\"8\" align=\"center\">".date("d/m/Y H:m:s")."</td>
                  </tr>
                  <tr>
                      <td colspan=\"8\">".$request."</td>
                  </tr>
                  <tr bgcolor=#DDDDDD>
                      <td>Table</td>
                      <td>Type</td>
                      <td>Possible_keys</td>
                      <td>key</td>
                      <td>key_len</td>
                      <td>ref</td>
                      <td>rows</td>
                      <td>Extra</td>
                  </tr>";
          while ($obj = $result->fetch_object()) {
                  $response .= "
                  <tr>
                      <td>&nbsp;".$obj->table."</td>
                      <td>&nbsp;".$obj->type."</td>
                      <td>&nbsp;".$obj->possible_keys."</td>
                      <td>&nbsp;".$obj->key."</td>
                      <td>&nbsp;".$obj->key_len."</td>
                      <td>&nbsp;".$obj->ref."</td>
                      <td>&nbsp;".$obj->rows."</td>
                      <td>&nbsp;".$obj->Extra."</td>
                  </tr>";
          }
          $response .= "</table>";
          
					        
          /* Log it into the logfile */
          //$file = new File($this->logfile,'w',null);
          //$file->write($response);
          
          if($outputFile = fopen($this->logFile,"a+")){
          fputs($outputFile,$response);
          fclose($outputFile); 
          }

       } catch(Exception $e) {
          $this->logs->logError($e->getMessage());
      }
    }
    
    /**
     * Retrieves server info
     *
     * @return string the server info
     */
    public function getInfoServer(){
      $this->connect();
        return "Server info : ".$this->connection->get_host_info();
    }

    /**
     * The destructor, closing the connection
     *
     */
    public function __destruct(){
      if($this->isConnected){
        try {
          $this->connection->close();
        } catch(Exception $e) {
          $this->logs->logWarning($e->getMessage());
        }
      }
    }    
    
    /**
     * Returns the number of queries done
     *
     * @return string number of queries
     */
    public function getNumQueries(){
        return $this->numQueries;
    }
    
    /**
     * Set if all MySQL queries must be Explained
     *
     * @param bool true if yes, false else
     */
    public function setExplainAll($explainAll){
        $this->explainAll = $explainAll;
    }
    
    /**
     * Returns if all MySQL queries are Explained
     *
     * @return bool
     */
    public function getExplainAll(){
        return $this->explainAll;
    }
    
    /**
     * Destroys mixed result of a query
     *
     * @param mixed $result
     */
    public function freeResult($result){
        $result->free_result();
    }
    
    /**
     * Retrieves the insert_id
     */         
    public function insert_id(){
        return $this->connection->insert_id();
    }
    
    /** 
     *  Connects to the database
     */         
    public function connect(){
      global $configDBhost;
  		global $configDBusername;
  		global $configDBpassword;
  		global $configDBdatabase;
  		global $configDBport;
  		
  		//if the connection exists
  		if(!$this->isConnected){
  		
        // Attempt to connect
        try {
           $this->connection = new sql($configDBhost, $configDBusername, $configDBpassword, $configDBdatabase, $configDBport);
          
            //Check the connection
            if ($this->connection->errno()) {
               //TODO : raise error
            }else{
              $this->isConnected = true;
            }
        } catch(Exception $e) {
            //throw new Exception($e->getMessage());
      	    //echo "Impossible de se connecter a la Base de Donnees";
      	    $this->logs->logEmergency($e->getMessage());
      	    exit(0);
        }
      }
    }
    
}
?>
